﻿using ICSharpCode.SharpZipLib.Checksum;
using ICSharpCode.SharpZipLib.Zip;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SHZY.BaseData.Entitys.Entity;
using SHZY.Business.Entitys.Dto.VideoRecording;
using SHZY.Business.Entitys.Entity.VideoRecording;
using SHZY.Business.Interfaces.VideoRecording;
using SHZY.ClayObject;
using SHZY.Common.Configuration;
using SHZY.Common.Core.Manager;
using SHZY.Common.Core.Manager.Files;
using SHZY.Common.Core.Security;
using SHZY.Common.Enum;
using SHZY.Common.Filter;
using SHZY.Common.Models.NPOI;
using SHZY.Common.Security;
using SHZY.DataEncryption;
using SHZY.DependencyInjection;
using SHZY.DynamicApiController;
using SHZY.FriendlyException;
using SHZY.Systems.Entitys.System;
using SHZY.Systems.Interfaces.System;
using SqlSugar;

namespace SHZY.Business.VideoRecording
{
    /// <summary>
    /// 业务实现：摄像机记录.
    /// </summary>
    [ApiDescriptionSettings(Tag = "system", Name = "QmsBusiCameraOrder", Order = 200)]
    [Route("api/system/[controller]")]
    public class QmsBusiCameraOrderService : IQmsBusiCameraOrderService, IDynamicApiController, ITransient
    {
        /// <summary>
        /// 服务基础仓储.
        /// </summary>
        private readonly ISqlSugarRepository<QmsBusiCameraOrderEntity> _repository;

        /// <summary>
        /// 多租户事务.
        /// </summary>
        private readonly ITenant _db;

        /// <summary>
        /// 数据接口服务.
        /// </summary>
        private readonly IDataInterfaceService _dataInterfaceService;

        /// <summary>
        /// 用户管理.
        /// </summary>
        private readonly IUserManager _userManager;

        /// <summary>
        /// 文件管理.
        /// </summary>
        private readonly IFileManager _fileManager;

        /// <summary>
        /// 初始化一个<see cref="QmsBusiCameraOrderService"/>类型的新实例.
        /// </summary>
        public QmsBusiCameraOrderService(
            ISqlSugarRepository<QmsBusiCameraOrderEntity> qmsBusiCameraOrderRepository,
            IDataInterfaceService dataInterfaceService,
            ISqlSugarClient context,
            IFileManager fileManager,
            IUserManager userManager)
        {
            _repository = qmsBusiCameraOrderRepository;
            _dataInterfaceService = dataInterfaceService;
            _db = context.AsTenant();
            _fileManager = fileManager;
            _userManager = userManager;
        }

        /// <summary>
        /// 获取摄像机记录.
        /// </summary>
        /// <param name="id">主键值.</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<dynamic> GetInfo(string id)
        {
            return (await _repository.FirstOrDefaultAsync(x => x.Id == id)).Adapt<QmsBusiCameraOrderInfoOutput>();
        }

        /// <summary>
        /// 获取摄像机记录列表.
        /// </summary>
        /// <param name="input">请求参数.</param>
        /// <returns></returns>
        [HttpGet("")]
        public async Task<dynamic> GetList([FromQuery] QmsBusiCameraOrderListQueryInput input)
        {

            string? AppUrl = string.IsNullOrEmpty(App.Configuration["SHZY_APP:AppUrl"]) ? string.Empty : App.Configuration["SHZY_APP:AppUrl"];
            string VideoPath = Path.Combine(KeyVariable.SystemPath, "VideoPath");
            var data = await _repository.Context.Queryable<QmsBusiCameraOrderEntity>().Where(w => w.DeleteMark == null && w.Column16 == null)
                .WhereIF(!string.IsNullOrEmpty(input.lineName), it => it.LineName.Contains(input.lineName))
                .WhereIF(!string.IsNullOrEmpty(input.ipAddress), it => it.IpAddress.Contains(input.ipAddress))
                .WhereIF(!string.IsNullOrEmpty(input.order), it => it.Order.Contains(input.order))
                .WhereIF(!string.IsNullOrEmpty(input.keyword), it => it.LineName.Contains(input.keyword) || it.IpAddress.Contains(input.keyword) || it.Order.Contains(input.keyword))
                .OrderByIF(string.IsNullOrEmpty(input.sidx), it => it.Id)
                .Select(it => new QmsBusiCameraOrderListOutput
                {
                    id = it.Id,
                    lineName = it.LineName,
                    ipAddress = it.IpAddress,
                    ipType=it.IpType,
                    order = it.Order,
                    startDate = it.StartDate,
                    endDate = it.EndDate,
                    operateUserId = SqlFunc.Subqueryable<BaseuserEntity>().Where(p => p.Id == it.OperateUserId).Select(p => p.RealName),
                    creatorUserId = SqlFunc.Subqueryable<BaseuserEntity>().Where(p => p.Id == it.CreatorUserId).Select(p => p.RealName),
                    fIle = SqlFunc.Replace(SqlFunc.Replace(it.FIle, ".mp4", "_1.mp4"), VideoPath, AppUrl) // 转码后的文件都带 _1  替换成网络路径访问
                }).OrderByIF(!string.IsNullOrEmpty(input.sidx), it => input.sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
            return PageResult<QmsBusiCameraOrderListOutput>.SqlSugarPageResult(data);
        }

        /// <summary>
        /// 新建摄像机记录（通过扫描操作次摄）.
        /// </summary>
        /// <param name="input">参数.</param>
        /// <returns></returns>
        [HttpPost("")]
        public async Task Create([FromBody] QmsBusiCameraOrderCrInput input)
        {
            QmsBaseCameraLineIpEntity cameraLineIpEntity = await _repository.Context.Queryable<QmsBaseCameraLineIpEntity>().Where(w => w.LineName == input.lineName && w.IpType == "主摄" && w.DeleteMark == null).FirstAsync();
            if (cameraLineIpEntity != null && cameraLineIpEntity.Status == 1)
            {
                int isOk = 0;
                QmsBusiCameraOrderEntity entity = input.Adapt<QmsBusiCameraOrderEntity>();
                DateTime dt = DateTime.Now;

                // 监听当前唛头是否已扫描
                QmsBusiCameraOrderEntity cameraOrderEntity = await _repository.Context.Queryable<QmsBusiCameraOrderEntity>().Where(w => w.LineName == input.lineName && w.IpAddress == input.ipAddress && w.Order == input.order && w.DeleteMark == null).FirstAsync();
                if (cameraOrderEntity == null)
                {
                    entity.Id = SnowflakeIdHelper.NextId();
                    entity.StartDate = dt;
                    string videoFilePath1 = Path.Combine(Path.Combine(KeyVariable.SystemPath, "VideoPath"), input.ipAddress + "\\");
                    entity.FIle = videoFilePath1 + input.order + ".mp4";
                    entity.OperateUserId = _userManager.UserId;

                    if (!Directory.Exists(videoFilePath1))
                    {
                        // 如果不存在就创建它
                        Directory.CreateDirectory(videoFilePath1);
                    }

                    await _repository.Context.Updateable<QmsBaseCameraLineIpEntity>().SetColumns(it => it.Status == 1).Where(it => it.LineName == input.lineName && it.IpAddress == input.ipAddress).ExecuteCommandAsync();
                    isOk = await _repository.Context.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
                }
                else
                {
                    if (cameraOrderEntity.EndDate != null)
                    {
                        throw Oops.Oh("当前唛头已操作完毕,请勿重复扫描!");
                    }

                    TimeSpan timeDifference = dt - Convert.ToDateTime(cameraOrderEntity.StartDate);
                    double seconds = timeDifference.TotalSeconds;

                    var query= await _repository.Context.Queryable<DictionaryTypeEntity>().LeftJoin<DictionaryTypeEntity>((a, b) => a.Id == b.ParentId).LeftJoin<DictionaryDataEntity>((a, b, c) => b.Id == c.DictionaryTypeId)
                                         .Where((a, b, c) => a.FullName == "录像管理" && b.FullName == "间隔时间" && a.DeleteMark == null && b.DeleteMark == null && c.DeleteMark == null).Select((a, b, c) => new { c.FullName }).FirstAsync();

                    if (query == null)
                    {
                        throw Oops.Oh("请配置录像扫描间隔时间!");
                    }

                    if (seconds < Convert.ToDouble(query.FullName))
                    {
                        throw Oops.Oh(string.Format("当前唛头两次扫描间隔需超过{0}s", Convert.ToDouble(query.FullName)));
                    }

                    // 次摄
                    await _repository.Context.Updateable<QmsBaseCameraLineIpEntity>().SetColumns(it => it.Status == 0).Where(it => it.LineName == input.lineName && it.IpAddress == input.ipAddress).ExecuteCommandAsync();
                    isOk = await _repository.Context.Updateable<QmsBusiCameraOrderEntity>().SetColumns(it => it.EndDate == dt).Where(it => it.Id == cameraOrderEntity.Id).ExecuteCommandAsync();

                    // 主摄重启
                    await _repository.Context.Updateable<QmsBaseCameraLineIpEntity>().SetColumns(it => it.Status == 0).Where(it => it.LineName == input.lineName && it.IpAddress == cameraLineIpEntity.IpAddress).ExecuteCommandAsync();
                    QmsBusiCameraOrderEntity cameraOrderTypeChieflyEntity = await _repository.Context.Queryable<QmsBusiCameraOrderEntity>().Where(w => w.LineName == input.lineName && w.IpType == "主摄" && w.EndDate == null && w.DeleteMark == null).FirstAsync();
                    if (cameraOrderTypeChieflyEntity != null)
                    {
                        await _repository.Context.Updateable<QmsBusiCameraOrderEntity>().SetColumns(it => new QmsBusiCameraOrderEntity() { EndDate = dt, Order = input.order }).Where(it => it.Id == cameraOrderTypeChieflyEntity.Id).ExecuteCommandAsync();
                    }

                    await _repository.Context.Updateable<QmsBaseCameraLineIpEntity>().SetColumns(it => it.Status == 1).Where(it => it.LineName == input.lineName && it.IpAddress == cameraLineIpEntity.IpAddress).ExecuteCommandAsync();

                    entity.Id = SnowflakeIdHelper.NextId();
                    entity.IpAddress = cameraLineIpEntity.IpAddress;
                    entity.IpType = "主摄";
                    entity.Order = dt.ToString("yyyyMMddHHmmss");
                    entity.StartDate = dt;
                    string videoFilePath = Path.Combine(Path.Combine(KeyVariable.SystemPath, "VideoPath"), entity.IpAddress + "\\");
                    entity.FIle = videoFilePath + entity.Order + ".mp4";
                    entity.OperateUserId = _userManager.UserId;

                    if (!Directory.Exists(videoFilePath))
                    {
                        // 如果不存在就创建它
                        Directory.CreateDirectory(videoFilePath);
                    }

                    await _repository.Context.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
                }

                if (!(isOk > 0)) throw Oops.Oh(ErrorCode.COM1000);
            }
            else
            {
                throw Oops.Oh("请开启主摄!");
            }
        }

        /// <summary>
        /// 获取摄像机记录无分页列表.
        /// </summary>
        /// <param name="input">请求参数.</param>
        /// <returns></returns>
        private async Task<dynamic> GetNoPagingList([FromQuery] QmsBusiCameraOrderListQueryInput input)
        {
            return await _repository.Context.Queryable<QmsBusiCameraOrderEntity>().Where(w => w.DeleteMark == null && w.Column16 == null)
                .WhereIF(!string.IsNullOrEmpty(input.lineName), it => it.LineName.Contains(input.lineName))
                .WhereIF(!string.IsNullOrEmpty(input.ipAddress), it => it.IpAddress.Contains(input.ipAddress))
                .WhereIF(!string.IsNullOrEmpty(input.order), it => it.Order.Contains(input.order))
                .WhereIF(!string.IsNullOrEmpty(input.keyword), it => it.LineName.Contains(input.keyword) || it.IpAddress.Contains(input.keyword) || it.Order.Contains(input.keyword))
                .OrderByIF(string.IsNullOrEmpty(input.sidx), it => it.Id)
                .Select(it => new QmsBusiCameraOrderListOutput
                {
                    id = it.Id,
                    lineName = it.LineName,
                    ipAddress = it.IpAddress,
                    ipType = it.IpType,
                    order = it.Order,
                    startDate = it.StartDate,
                    endDate = it.EndDate,
                    operateUserId = SqlFunc.Subqueryable<BaseuserEntity>().Where(p => p.Id == it.OperateUserId).Select(p => p.RealName),
                    creatorUserId = SqlFunc.Subqueryable<BaseuserEntity>().Where(p => p.Id == it.CreatorUserId).Select(p => p.RealName),
                }).OrderByIF(!string.IsNullOrEmpty(input.sidx), it => input.sidx + " " + input.sort).ToListAsync();
        }

        /// <summary>
        /// 导出摄像机记录.
        /// </summary>
        /// <param name="input">请求参数.</param>
        /// <returns></returns>
        [HttpGet("Actions/Export")]
        public async Task<dynamic> Export([FromQuery] QmsBusiCameraOrderListQueryInput input)
        {
            var exportData = new List<QmsBusiCameraOrderListOutput>();
            if (input.dataType == 0)
                exportData = Clay.Object(await GetList(input)).Solidify<PageResult<QmsBusiCameraOrderListOutput>>().list;
            else
                exportData = await GetNoPagingList(input);
            List<ParamsModel> paramList = "[{\"value\":\"产线名称\",\"field\":\"lineName\"},{\"value\":\"IP地址\",\"field\":\"ipAddress\"},{\"value\":\"录像类型\",\"field\":\"ipType\"},{\"value\":\"订单唛头\",\"field\":\"order\"},{\"value\":\"开始日期\",\"field\":\"startDate\"},{\"value\":\"结束日期\",\"field\":\"endDate\"},{\"value\":\"操作人\",\"field\":\"operateUserId\"},{\"value\":\"扫描人\",\"field\":\"creatorUserId\"},]".ToList<ParamsModel>();
            ExcelConfig excelconfig = new ExcelConfig();
            excelconfig.FileName = "摄像机记录.xls";
            excelconfig.HeadFont = "微软雅黑";
            excelconfig.HeadPoint = 10;
            excelconfig.IsAllSizeColumn = true;
            excelconfig.ColumnModel = new List<ExcelColumnModel>();
            foreach (var item in input.selectKey.Split(',').ToList())
            {
                var isExist = paramList.Find(p => p.field == item);
                if (isExist != null)
                    excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = isExist.field, ExcelColumn = isExist.value });
            }

            var addPath = FileVariable.TemporaryFilePath + excelconfig.FileName;
            ExcelExportHelper<QmsBusiCameraOrderListOutput>.Export(exportData, excelconfig, addPath);
            var fileName = _userManager.UserId + "|" + addPath + "|xls";
            return new
            {
                name = excelconfig.FileName,
                url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "SHZY")
            };
        }

        /// <summary>
        /// 批量删除摄像机记录.
        /// </summary>
        /// <param name="ids">主键数组.</param>
        /// <returns></returns>
        [HttpPost("batchRemove")]
        public async Task BatchRemove([FromBody] List<string> ids)
        {
            var entitys = await _repository.Context.Queryable<QmsBusiCameraOrderEntity>().In(it => it.Id, ids).ToListAsync();
            if (entitys.Count > 0)
            {
                try
                {
                    // 开启事务
                    _db.BeginTran();

                    // 批量删除摄像机记录
                    var isOk = await _repository.Context.Updateable<QmsBusiCameraOrderEntity>().SetColumns(it => new QmsBusiCameraOrderEntity()
                    {
                        DeleteTime = DateTime.Now,
                        DeleteMark = 1,
                        DeleteUserId = _userManager.UserId
                    }).Where(it => ids.Contains(it.Id)).ExecuteCommandHasChangeAsync();

                    // 关闭事务
                    _db.CommitTran();
                }
                catch (Exception)
                {
                    // 回滚事务
                    _db.RollbackTran();

                    throw Oops.Oh(ErrorCode.COM1002);
                }
            }
        }

        /// <summary>
        /// 更新摄像机记录（操作主摄）.
        /// </summary>
        /// <param name="id">主键值.</param>
        /// <param name="input">参数.</param>
        /// <returns></returns>
        [HttpPut("")]
        public async Task Update([FromBody] QmsBusiCameraOrderUpInput input)
        {
            // 已开启-->关闭  未开启-->启动
            var lineIpEntity = await _repository.Context.Queryable<QmsBaseCameraLineIpEntity>().Where(it => it.LineName == input.lineName && it.IpAddress == input.ipAddress && it.DeleteMark == null).FirstAsync();
            int isOk = 0;
            if (lineIpEntity != null)
            {
                if (lineIpEntity.Status == 0)
                {

                    QmsBusiCameraOrderEntity entity = input.Adapt<QmsBusiCameraOrderEntity>();
                    DateTime dt = DateTime.Now;
                    entity.Id = SnowflakeIdHelper.NextId();
                    entity.Order = dt.ToString("yyyyMMddHHmmss");
                    entity.StartDate = dt;
                    string videoFilePath = Path.Combine(Path.Combine(KeyVariable.SystemPath, "VideoPath"), input.ipAddress + "\\");
                    entity.FIle = videoFilePath + entity.Order + ".mp4";
                    entity.OperateUserId = _userManager.UserId;

                    if (!Directory.Exists(videoFilePath))
                    {
                        // 如果不存在就创建它
                        Directory.CreateDirectory(videoFilePath);
                    }

                    // 必须先更改其状态再操作记录表，涉及触发器先后顺序
                    isOk = await _repository.Context.Updateable<QmsBaseCameraLineIpEntity>().SetColumns(it => it.Status == 1).Where(it => it.Id == lineIpEntity.Id).ExecuteCommandAsync();
                    await _repository.Context.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
                }
                else
                {
                    QmsBusiCameraOrderEntity cameraOrderTypeChieflyEntity = await _repository.Context.Queryable<QmsBusiCameraOrderEntity>().Where(w => w.LineName == input.lineName && w.IpType == "主摄" && w.EndDate == null && w.DeleteMark == null).FirstAsync();
                    if (cameraOrderTypeChieflyEntity != null)
                    {
                        // 必须先更改其状态再操作记录表，涉及触发器先后顺序
                        isOk = await _repository.Context.Updateable<QmsBaseCameraLineIpEntity>().SetColumns(it => it.Status == 0).Where(it => it.Id == lineIpEntity.Id).ExecuteCommandAsync();
                        await _repository.Context.Updateable<QmsBusiCameraOrderEntity>().SetColumns(it => new QmsBusiCameraOrderEntity() { EndDate = DateTime.Now, Column16 = "1" }).Where(it => it.Id == cameraOrderTypeChieflyEntity.Id).ExecuteCommandAsync();
                    }
                }
            }

            if (!(isOk > 0)) throw Oops.Oh(ErrorCode.COM1001);
        }

        /// <summary>
        /// 删除摄像机记录.
        /// </summary>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task Delete(string id)
        {
            var isOk = await _repository.Context.Updateable<QmsBusiCameraOrderEntity>().SetColumns(it => new QmsBusiCameraOrderEntity()
            {
                DeleteTime = DateTime.Now,
                DeleteMark = 1,
                DeleteUserId = _userManager.UserId
            }).Where(x => x.Id == id).ExecuteCommandHasChangeAsync();
            if (!isOk)
                throw Oops.Oh(ErrorCode.COM1002);
        }

        /// <summary>
        /// 模板下载.
        /// </summary>
        /// <returns></returns>
        [HttpGet("DownloadFiles")]
        public async Task<FileStreamResult> DownloadFiles(string pathUrl)
        {
            return await _fileManager.DownloadFileByType(pathUrl, Path.GetFileName(pathUrl));
        }
    }

}
